/* 
 * Created by 2019年4月17日
 */
package com.edev.support.dao;

import com.edev.support.entity.Entity;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 基础DAO接口（通用CRUD操作）
 * <p>
 * 核心功能：
 * 1. 提供实体类的通用持久化操作
 * 2. 支持批量操作和条件查询
 * 3. 实现基于模板的灵活数据访问
 * <p>
 * 泛型说明：
 * @param <E> 实体类型（需继承Entity）
 * @param <S> 序列化ID类型（如Long/String）
 * <p>
 * 典型使用场景：
 * - 快速实现领域对象的持久化层
 * - 构建通用数据访问服务
 * - 复杂查询条件动态组装
 * @see com.edev.support.dao.impl.BasicDaoImpl 具体实现类
 * @author fangang
 */
public interface BasicDao {
	/**
     * 插入单个实体到数据库表中，并返回生成的主键。
     * @param entity 待插入的实体对象（必须包含所有非空字段）
     * @return 插入后生成的主键
     * @throws DataAccessException 数据库访问异常时抛出
     */
    <E extends Entity<S>, S extends Serializable> S insert(E entity);
    
    /**
     * 更新现有实体
     * 实现逻辑：
     * 1. 根据实体主键定位记录
     * 2. 更新所有非主键字段
     * @param entity 待更新的实体对象（必须包含有效主键）
     * @throws DataAccessException 记录不存在或数据库访问异常时抛出
     */
    <E extends Entity<S>, S extends Serializable> void update(E entity);
    
    /**
     * 插入或更新实体（根据数据库中的数据自动判断）
     * 执行流程：
     * 1. 先尝试执行插入操作（主键冲突则捕获异常）
     * 2. 如果插入失败，则执行更新操作
     * @param entity 待操作的实体对象
     * @return 最终持久化后的主键
     * @throws DataAccessException 违反唯一约束等数据库异常时抛出
     */
    <E extends Entity<S>, S extends Serializable> S insertOrUpdate(E entity);
    /**
     * 根据模板条件删除实体记录
     * 使用方式：
     * 1. 创建实体模板并设置条件字段
     * 2. 非空字段将作为删除条件（AND连接）
     * 示例：
     * <pre>
     * User template = new User();
     * template.setStatus("DELETED"); // 删除所有状态为DELETED的用户
     * dao.delete(template);
     * </pre>
     * @param template 条件模板实体（非空字段作为删除条件）
     * @throws DataAccessException 数据库操作异常时抛出
     */
    <E extends Entity<S>, S extends Serializable> void delete(E template);
    /**
     * 批量插入或更新实体列表
     * 实现逻辑：
     * 1. 遍历列表中的每个实体
     * 2. 根据主键存在性自动判断插入或更新
	 * 3. 所有批量的操作都在同一事务中
     * 注意：
     * - 列表大小影响性能，建议合理安排批量大小，分批处理数据
     * @param list 实体对象集合（需保证主键有效性）
     */
    <E extends Entity<S>, S extends Serializable, C extends Collection<E>> void insertOrUpdateForList(C list);
    /**
     * 批量删除实体列表
     * 实现方式：
     * 1. 遍历列表中的每个实体
     * 2. 根据实体主键执行删除
     * 注意：
     * - 本方法通过实体对象获取主键，适用于已加载实体列表的场景
     * @param list 待删除的实体集合
     */
    <E extends Entity<S>, S extends Serializable, C extends Collection<E>> void deleteForList(C list);
    /**
     * 根据主键和实体类删除记录
     * 适用场景：
     * - 已知主键但未加载实体对象时
     * - 需要根据类型信息确定元数据时
     * @param id 实体主键值
     * @param clazz 实体类类型（用于获取表结构信息）
     * @throws DataAccessException 记录不存在时抛出异常
     */
    <E extends Entity<S>, S extends Serializable> void delete(S id, Class<E> clazz);
	/**
     * 根据主键加载单个实体
     * @param id 实体主键值
     * @param clazz 实体类类型（用于确定元数据）
     * @return 查找到的实体对象（未找到返回null）
     * @throws DataAccessException 数据库访问异常时抛出
     */
    <E extends Entity<S>, S extends Serializable> E load(S id, Class<E> clazz);
	/**
     * 根据主键列表批量删除实体记录
     * 实现方式：
     * 1. 生成IN条件语句（WHERE id IN (?,?,?)）
     * 2. 执行批量删除操作
	 * 3. 所有批量的操作都在同一事务中
     * 注意：
     * - 空列表将不执行任何操作
     * @param ids 主键集合
     * @param clazz 实体类类型（用于获取表结构信息）
     */
    <E extends Entity<S>, S extends Serializable> void deleteForList(Collection<S> ids, Class<E> clazz);
	/**
     * 根据主键列表批量加载实体
     * 实现逻辑：
     * 1. 生成IN条件语句（WHERE id IN (?,?,?)）
     * 2. 返回结果集保持与输入ID列表顺序一致
     * @param ids 主键集合
     * @param clazz 实体类类型
     * @return 实体对象集合（未找到的ID不出现在结果集中）
     */
    <E extends Entity<S>, S extends Serializable> Collection<E> loadForList(Collection<S> ids, Class<E> clazz);
	/**
     * 基于模板的条件查询（AND逻辑连接）
     * 使用示例：
     * <pre>
     * OrderItem template = new OrderItem();
     * template.setOrderId(1001L);
     * Collection<OrderItem> items = dao.loadAll(template);
     * </pre>
     * @param template 条件模板（非空字段作为查询条件）
     * @return 符合条件的实体集合（无结果返回空集合）
     */
    <E extends Entity<S>, S extends Serializable> Collection<E> loadAll(E template);
	/**
     * 基于列映射的复杂条件查询
     * 条件格式示例：
     * <pre>
     * [
     *   {"key":"createTime", "opt":">=", "value":"2024-01-01"},
     *   {"key":"status", "opt":"IN", "value":[1,2,3]}
     * ]
     * </pre>
     * @param colMap 条件列表（支持=,>,<,>=,<=,!=,LIKE,IN等操作符，不设置opt时默认为=）
     * @param clazz 实体类类型
     * @return 符合条件的实体集合（无结果返回空集合）
     * @throws IllegalArgumentException 条件格式错误时抛出
     */
    <E extends Entity<S>, S extends Serializable> Collection<E> loadAll(List<Map<Object, Object>> colMap, Class<E> clazz);
}
